﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using HeritageAcademy.Models.ViewModels;

namespace HeritageAcademy.Library.Controls
{
    /// <summary>
    /// Interaction logic for Book.xaml
    /// </summary>
    public partial class LibraryBookView
    {
        #region Fields 
        static int bookAnimationCounter;
        static LibraryBookVisualCollection BookVisuals;
        bool isHidden;
        static readonly Random R = new Random();
        CourseViewModel viewModel;
        #endregion Fields 

        #region Ctor 
        public LibraryBookView()
        {
            InitializeComponent();
            DataContextChanged += LibraryBook_DataContextChanged;

            if (BookVisuals == null)
                BookVisuals = TryFindResource("BookVisuals") as LibraryBookVisualCollection;
        }
        #endregion

        #region Event Handlers 
        void LibraryBook_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            viewModel = e.NewValue as CourseViewModel;
            InitializeVisual();
        }

        private void ShowHide_Completed(object sender, EventArgs e)
        {
            TryAnimationCompleted();
        }
        #endregion

        #region Public Methods 
        public void HideDetails()
        {
            var hide = Resources["HideDetails"] as Storyboard;
            if (hide != null) hide.Begin(this);
        }

        public void ShowDetails()
        {
            var show = Resources["ShowDetails"] as Storyboard;
            if (show != null) show.Begin(this);
        }
        #endregion Public Methods 

        #region Private Methods 
        private void InitializeVisual()
        {
            if (viewModel == null) return;
            if (BookVisuals == null) return;

            // create a visual a Random value seeded with reliabled data (so that the book always looks the same) 
            int seed = viewModel.Model.Title.Length * viewModel.FlatChapters.Count + 5;
            Random R = new Random(seed);
            int bookIndex = R.Next(0, BookVisuals.Count);
            LibraryBookVisual visual = BookVisuals[bookIndex];

            // make sure that the title fits
            int longestWord = viewModel.Model.Title.Split(new char[] { ' ' }).Max(word => word.Length);
            int loopcount = 0;
            while ((viewModel.Model.Title.Length > visual.MaxTitleLength || longestWord > visual.MaxWordLength))
            {
                bookIndex = R.Next(0, BookVisuals.Count);
                visual = BookVisuals[bookIndex];
                loopcount++;

                if (loopcount >= 200)
                {
                    visual = null;
                    break;
                }
            }

            if (visual == null) return;

            // set the image associated with the book
            BookImage.Source = visual.Source;

            // configure the title rect
            TitleSite.SetValue(Canvas.LeftProperty, visual.TextLocation.Left);
            TitleSite.SetValue(Canvas.TopProperty, visual.TextLocation.Top);
            TitleSite.Width = visual.TextLocation.Width;
            TitleSite.Height = visual.TextLocation.Height;

            // configure the title text
            BookTitleText.Text = viewModel.Model.Title;
            BookTitleText.Foreground = visual.Foreground;
            BookTitleText.FontSize = visual.FontSize;

            if (visual.TextOrientation == Orientation.Vertical)
            {
                TitleSiteRotation.Angle = 90.0;
                BookTitleText.MaxWidth = visual.TextLocation.Height;
                BookTitleText.VerticalAlignment = VerticalAlignment.Top;
                BookTitleText.TextAlignment = TextAlignment.Left;
            }
            else
            {
                TitleSiteRotation.Angle = 0.0;
                BookTitleText.MaxWidth = visual.TextLocation.Width;
                BookTitleText.VerticalAlignment = VerticalAlignment.Center;
                BookTitleText.TextAlignment = TextAlignment.Center;
            }
        }

        private void TryAnimationCompleted()
        {
            bookAnimationCounter--;

            if (bookAnimationCounter == 0)
            {
                //RoundingStackPanel p = Helpers.TreeHelpers.FindFirstLogicalOrVisualParentOfType<RoundingStackPanel>(this);
                //if (p != null)
                //{
                //    p.IsRoundingEnabled = true;
                //}
                RaiseGlobalAnimationCompleted();
            }
        }

        private void TryAnimationStarted()
        {
            if (bookAnimationCounter == 0)
            {
                //RoundingStackPanel p = Helpers.TreeHelpers.FindFirstLogicalOrVisualParentOfType<RoundingStackPanel>(this);
                //if (p != null)
                //{
                //    p.IsRoundingEnabled = false;
                //}
                RaiseGlobalAnimationStarted();
            }

            bookAnimationCounter++;
        }
        #endregion
        
        #region GlobalAnimationStarted

        public static event EventHandler GlobalAnimationStarted;

        private static void RaiseGlobalAnimationStarted()
        {
            if (GlobalAnimationStarted != null)
            {
                GlobalAnimationStarted(null, new EventArgs());
            }
        }

        #endregion
        
        #region GlobalAnimationCompleted

        public static event EventHandler GlobalAnimationCompleted;

        private static void RaiseGlobalAnimationCompleted()
        {
            if (GlobalAnimationCompleted != null)
            {
                GlobalAnimationCompleted(null, new EventArgs());
            }
        }

        #endregion
        
        #region IsFiltered

        /// <summary>
        /// IsFiltered Dependency Property
        /// </summary>
        public static readonly DependencyProperty IsFilteredProperty =
            DependencyProperty.Register("IsFiltered", typeof(bool), typeof(LibraryBookView),
                new FrameworkPropertyMetadata((bool)true,
                    new PropertyChangedCallback(OnIsFilteredChanged)));

        /// <summary>
        /// Gets or sets the IsFiltered property.  This dependency property 
        /// indicates ....
        /// </summary>
        public bool IsFiltered
        {
            get { return (bool)GetValue(IsFilteredProperty); }
            set { SetValue(IsFilteredProperty, value); }
        }

        /// <summary>
        /// Handles changes to the IsFiltered property.
        /// </summary>
        private static void OnIsFilteredChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((LibraryBookView)d).OnIsFilteredChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the IsFiltered property.
        /// </summary>
        protected virtual void OnIsFilteredChanged(DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue)
            {
                if (!isHidden) return;
                Storyboard show = this.Resources["ShowStoryboard"] as Storyboard;
                if (show != null)
                {
                    show.BeginTime = show.BeginTime.Value.Add(TimeSpan.FromMilliseconds(R.Next(-3, 4) * 30));
                    isHidden = false;
                    show.Begin(this);
                    TryAnimationStarted();
                }
            }
            else
            {
                if (isHidden) return;
                Storyboard hide = this.Resources["HideStoryboard"] as Storyboard;
                if (hide != null)
                {
                    //hide.BeginTime = hide.BeginTime.Value.Add(TimeSpan.FromMilliseconds(R.Next(-3, 4) * 20));
                    isHidden = true;
                    hide.Begin(this);
                    TryAnimationStarted();
                }
            }
        }

        #endregion

        #region IsDetailVisible

        public static readonly DependencyProperty IsDetailVisibleProperty =
            DependencyProperty.Register("IsDetailVisible", typeof(bool), typeof(LibraryBookView),
                new FrameworkPropertyMetadata((bool)false,
                    new PropertyChangedCallback(OnIsDetailVisibleChanged)));

        public bool IsDetailVisible
        {
            get { return (bool)GetValue(IsDetailVisibleProperty); }
            set { SetValue(IsDetailVisibleProperty, value); }
        }

        private static void OnIsDetailVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((LibraryBookView)d).OnIsDetailVisibleChanged(e);
        }

        protected virtual void OnIsDetailVisibleChanged(DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue)
            {
                ShowDetails();
            }
            else
            {
                HideDetails();
            }
        }

        #endregion
    }
}
